import { defineComponent, onMounted, reactive, ref } from "vue";
import MusicSongBranchService from "../index.service";
import to from "await-to-js";
import { useRoute, useRouter } from "vue-router";
import { useStore as useTagsStore } from "@/store/tags";
import fetchBase64AsUint8Array from "@/common/utils/fetchBase64AsUint8Array";
import pako from "pako";
import styles from "./index.module.less";
import { LoadingOutlined, PlusOutlined, UploadOutlined, FileOutlined, CaretRightOutlined } from "@ant-design/icons-vue";
import { $upload } from "@/apis/common/upload/upload";
import { message, Modal } from "ant-design-vue";
import eventBus from "@/common/eventBus/mitt";
import uint8Array2Base64 from "@/common/utils/uint8Array2Base64";
import _ from "lodash";
export default defineComponent({
  name: "BranchModify",
  setup() {
    const musicSongBranchService = new MusicSongBranchService();
    const route = useRoute();
    const router = useRouter();
    const tagsStore = useTagsStore();
    const state = reactive({
      id: null as any,
      form: {
        name: null,
        poster: null,
        midFile: null,
        sort: 0,
        status: 0,
        content: [
          {
            name: 2,
            children: [] as any[],
          },
          {
            name: 4,
            children: [] as any[],
          },
        ],
        contentStr: null as string | null,
      },
      types: [
        {
          label: "树形编辑器",
          value: "tree",
        },
        {
          label: "输入框",
          value: "json",
        },
      ],
      type: "tree",
      poster_loading: false,
      midFile_loading: false,
    })
    const getDetail = async () => {
      const [err, res]: any = await to(musicSongBranchService.detail(state.id));
      if (!err) {
        const resultObj = res.data.data || {};
        state.form.name = resultObj?.name || null;
        state.form.poster = resultObj?.poster || null;
        state.form.midFile = resultObj?.midFile || null;
        state.form.sort = resultObj?.sort || 0;
        state.form.status = resultObj?.status || 0;
        let events_pako_return = "";
        const uint8Arr = await fetchBase64AsUint8Array(resultObj?.content);
        events_pako_return = new TextDecoder().decode(pako.inflate(uint8Arr));
        events_pako_return = decodeURIComponent(events_pako_return);
        const contentJson = JSON.parse(events_pako_return);
        let events_pako_return2 = "";
        const uint8Arr2 = await fetchBase64AsUint8Array(resultObj?.contentTwoFour);
        events_pako_return2 = new TextDecoder().decode(pako.inflate(uint8Arr2));
        events_pako_return2 = decodeURIComponent(events_pako_return2);
        const contentJson2 = JSON.parse(events_pako_return2);
        state.form.content[0].children = Object.entries(contentJson2).map(x => {
          return {
            name: x[0],
            children: x[1],
          }
        })
        state.form.content[1].children = Object.entries(contentJson).map(x => {
          return {
            name: x[0],
            children: x[1],
          }
        });
        const json = {
          "2": contentJson2,
          "4": contentJson,
        }
        state.form.contentStr = JSON.stringify(json);
      }
    }
    onMounted(() => {
      state.id = route.query?.id || null;
      if (state.id) {
        getDetail();
      }
    })
    // 上传图片
    const beforeUpload = async (file) => {
      state.poster_loading = true;
      const formData = new FormData();
      formData.append("file", file);
      const [err, res]: any = await to($upload(formData));
      if (err) {
        state.form.poster = null;
        state.poster_loading = false;
        return;
      }
      state.form.poster = res.data?.data?.ossUpload?.fileUrl || "";
      state.poster_loading = false;
      return false;
    }
    // 上传mid文件
    const beforeUploadMidFile = async (file) => {
      state.midFile_loading = true;
      const formData = new FormData();
      formData.append("file", file);
      const [err, res]: any = await to($upload(formData));
      if (err) {
        state.form.midFile = null;
        state.midFile_loading = false;
        return;
      }
      state.form.midFile = res.data?.data?.ossUpload?.fileUrl || null;
      state.midFile_loading = false;
      return false;
    }
    const temp = reactive({
      chord_name: null,
      group: {
        Note: null,
        Velocity: null,
        duration: null,
      }
    })
    // 添加和弦
    const addChord = (indexX, indexY = null) => {
      Modal.confirm({
        title: '添加和弦',
        content: () => <div class={styles.signRow}><input placeholder="请输入和弦名" v-model={temp.chord_name} /></div>,
        onOk: () => {
          if (!temp.chord_name) {
            message.error("请输入和弦名!");
            temp.chord_name = null;
            return;
          }
          if (state.form?.content?.[indexX]?.children?.map?.(x => x.name)?.includes?.(temp.chord_name)) {
            message.error("已有该和弦!");
            temp.chord_name = null;
            return;
          }
          if (indexY === null) {
            state.form?.content?.[indexX]?.children.push({
              name: temp.chord_name,
              children: [],
            })
          } else {
            state.form?.content?.[indexX]?.children.splice(indexY, 0, {
              name: temp.chord_name,
              children: [],
            })
          }
          temp.chord_name = null;
        },
        onCancel: () => {
          temp.chord_name = null;
        },
      });
    }
    // 初始化group
    const initGroup = () => {
      temp.group.Note = null;
      temp.group.Velocity = null;
      temp.group.duration = null;
    }
    // 添加小节
    const addGroup = (indexX, indexY, e = null as any, indexZ = null as any) => {
      if (e) {
        temp.group.Note = e.Note || null;
        temp.group.Velocity = e.Velocity || null;
        temp.group.duration = e.duration || null;
      }
      Modal.confirm({
        title: e ? '编辑小节' : '添加小节',
        content: () => <div class={styles.signRow}>
          <input placeholder="请输入Note" v-model={temp.group.Note} />
          <input placeholder="请输入Velocity" v-model={temp.group.Velocity} />
          <input placeholder="请输入duration" v-model={temp.group.duration} />
        </div>,
        onOk: () => {
          if (!temp.group.Note) {
            message.error("请输入Note!");
            initGroup();
            return;
          }
          if (!temp.group.Velocity) {
            message.error("请输入Velocity!");
            initGroup();
            return;
          }
          if (!temp.group.duration) {
            message.error("请输入duration!");
            initGroup();
            return;
          }
          if (e) {
            state.form.content[indexX].children[indexY].children[indexZ].Note = temp.group.Note;
            state.form.content[indexX].children[indexY].children[indexZ].Velocity = temp.group.Velocity;
            state.form.content[indexX].children[indexY].children[indexZ].duration = temp.group.duration;
          } else if (indexZ === null) {
            state.form?.content?.[indexX]?.children?.[indexY]?.children?.push({
              Note: temp.group.Note,
              Velocity: temp.group.Velocity,
              duration: temp.group.duration,
            })
          } else {
            state.form?.content?.[indexX]?.children?.[indexY]?.children?.splice(indexZ, 0, {
              Note: temp.group.Note,
              Velocity: temp.group.Velocity,
              duration: temp.group.duration,
            })
          }
          initGroup();
        },
        onCancel: () => {
          initGroup();
        },
      });
    }
    // 删除和弦
    const delChord = (indexX, indexY) => {
      state.form?.content?.[indexX]?.children?.splice(indexY, 1);
    }
    // 删除小节
    const delGroup = (indexX, indexY, indexZ) => {
      state.form?.content?.[indexX]?.children?.[indexY]?.children?.splice(indexZ, 1);
    }
    const getContent = async (jsonStr) => {
      try {
        const json = JSON.parse(jsonStr);
        const contentTwoFourJson = json?.["2"];
        const contentJson = json?.["4"];
        return [contentTwoFourJson, contentJson];
      } catch (err) {
        return [null, null];
      }
    }
    // 提交
    const submit = async () => {
      formRef.value
        .validate()
        .then(async () => {
          let contentObj = {};
          let contentTwoFourObj = {};
          if (state.type === 'tree') {
            if (state.form.content[0].children.length === 0 && state.form.content[1].children.length === 0) {
              message.error("请填写内容!");
              return;
            }
            state.form.content[0].children.forEach(x => {
              contentTwoFourObj[x.name] = x.children;
            })
            state.form.content[1].children.forEach(x => {
              contentObj[x.name] = x.children;
            })
          } else {
            const [contentTwoFour, content] = await getContent(state.form.contentStr);
            if (!contentTwoFour || !content) {
              message.error("内容JSON有误,请重新填写!");
              return;
            }
            contentObj = content;
            contentTwoFourObj = contentTwoFour;
          }
          const contentTwoFourObjStr = JSON.stringify(contentTwoFourObj);
          let event = encodeURIComponent(contentTwoFourObjStr);
          let events_pako = pako.deflate(event);
          let contentTwoFour: any = await uint8Array2Base64(events_pako);
          const contentObjStr = JSON.stringify(contentObj);
          let event2 = encodeURIComponent(contentObjStr);
          let events_pako2 = pako.deflate(event2);
          let content: any = await uint8Array2Base64(events_pako2);
          const params = {
            id: state.id || undefined,
            name: state.form.name,
            poster: state.form.poster,
            contentTwoFour,
            content,
            midFile: state.form.midFile,
            sort: state.form.sort,
            status: state.form.status,
          }
          const [err, res]: any = await to((state.id ? musicSongBranchService.edit : musicSongBranchService.add)(params as any));
          if (!err) {
            message.success(state.id ? '编辑成功' : '添加成功');
            eventBus.branchModifyFinish.emit();
            tagsStore.removeTagSimple(route.name);
            router.go(-1);
          }
        })
    }
    const formRef = ref(null as any);
    const typeChange = (item) => {
      state.type = item.value;
    }
    return () => (
      <div class={styles.branchModify}>
        <div class={styles.wallPaper}>
          <a-form ref={formRef} model={state.form} label-col={{ style: { width: '150px' } }} wrapper-col={{ span: 20 }}>
            <a-form-item required label="名称" name="name">
              <a-input style={{ width: "200px" }} v-model:value={state.form.name} placeholder="请填写伴奏支体名称" />
            </a-form-item>
            <a-form-item required label="图片" name="poster">
              <a-upload show-upload-list={false} before-upload={beforeUpload} list-type="picture-card" class={styles['avatar-uploader']}>
                {
                  state.form.poster
                    ?
                    <a-image preview={false} width={128} src={state.form.poster} />
                    :
                    <div>
                      {
                        state.poster_loading ? <LoadingOutlined /> : <PlusOutlined />
                      }
                      <div class={styles['ant-upload-text']}>上传图片</div>
                    </div>
                }
              </a-upload>
            </a-form-item>
            <a-form-item required label="mid文件" name="midFile">
              <a-upload show-upload-list={false} before-upload={beforeUploadMidFile}>
                <a-button>
                  {state.midFile_loading ? <LoadingOutlined /> : <UploadOutlined />}
                  上传文件
                </a-button>
              </a-upload>
              <div class={styles.midFile}>
                <FileOutlined />
                <span class={styles.fileNameBox}>
                  {state.form.midFile ? <span class={styles.fileName}>{state.form.midFile}</span> : <span class={styles.noFile}>暂未上传</span>}
                </span>
              </div>
            </a-form-item>
            <a-form-item label="排序" name="sort">
              <a-input-number style={{ width: "200px" }} min={0} v-model:value={state.form.sort} placeholder="请填写排序" />
            </a-form-item>
            <a-form-item label="状态" name="status">
              <a-radio-group>
                <a-radio-group v-model:value={state.form.status} name="radioGroup">
                  <a-radio value={0}>上架</a-radio>
                  <a-radio value={1}>下架</a-radio>
                </a-radio-group>
              </a-radio-group>
            </a-form-item>
            <a-form-item label="上传方式">
              <div class={styles.types}>
                {
                  state.types.map((item) => (
                    <div class={[styles.type, item.value === state.type && styles.checked]} onClick={() => { typeChange(item) }}>{item.label}</div>
                  ))
                }
              </div>
            </a-form-item>
            {
              state.type === 'tree' ? <a-form-item label="内容" name="content">
                <div class={styles.contentBox}>
                  {
                    state.form.content.map((itemX: any, indexX) => (
                      <div class={styles.levelBox}>
                        <a-dropdown trigger="contextmenu" placement="bottomRight" v-slots={{
                          overlay: () => <>
                            <a-menu>
                              <a-menu-item key="1" onClick={() => { addChord(indexX) }}>添加和弦</a-menu-item>
                            </a-menu>
                          </>
                        }}>
                          <div class={styles.level} onClick={() => { itemX.expand = !itemX.expand }}>
                            <CaretRightOutlined class={[styles.icon, itemX.expand && styles.expand]} /><span>{itemX.name}</span>
                          </div>
                        </a-dropdown>
                        {
                          itemX.children.map((itemY: any, indexY) => (
                            <div class={[styles.levelBox, styles['pl-15']]} style={{ display: itemX.expand ? 'flex' : 'none' }}>
                              <a-dropdown trigger="contextmenu" placement="bottomRight" v-slots={{
                                overlay: () => <>
                                  <a-menu>
                                    <a-menu-item key="1" onClick={() => { addGroup(indexX, indexY) }}>添加小节</a-menu-item>
                                    <a-menu-item key="2" onClick={() => { addChord(indexX, indexY) }}>前插和弦</a-menu-item>
                                    <a-menu-item key="3" onClick={() => { addChord(indexX, indexY + 1) }}>后插和弦</a-menu-item>
                                    <a-menu-item key="4" onClick={() => { delChord(indexX, indexY) }}>删除和弦</a-menu-item>
                                  </a-menu>
                                </>
                              }}>
                                <div class={styles.level} onClick={() => { itemY.expand = !itemY.expand }}>
                                  <CaretRightOutlined class={[styles.icon, itemY.expand && styles.expand]} /><span>{itemY.name}</span>
                                </div>
                              </a-dropdown>
                              {
                                itemY.children.map((itemZ: any, indexZ) => (
                                  <div class={[styles.levelBox, styles['pl-15']]} style={{ display: itemY.expand ? 'flex' : 'none' }}>
                                    <a-dropdown trigger="contextmenu" placement="bottomRight" v-slots={{
                                      overlay: () => <>
                                        <a-menu>
                                          <a-menu-item key="1" onClick={() => { addGroup(indexX, indexY, { Note: itemZ.Note, Velocity: itemZ.Velocity, duration: itemZ.duration }, indexZ) }}>编辑小节</a-menu-item>
                                          <a-menu-item key="2" onClick={() => { addGroup(indexX, indexY, null, indexZ) }}>前插小节</a-menu-item>
                                          <a-menu-item key="3" onClick={() => { addGroup(indexX, indexY, null, indexZ + 1) }}>后插小节</a-menu-item>
                                          <a-menu-item key="4" onClick={() => { delGroup(indexX, indexY, indexZ) }}>删除小节</a-menu-item>
                                        </a-menu>
                                      </>
                                    }}>
                                      <div class={styles.level} onClick={() => { itemZ.expand = !itemZ.expand }}>
                                        <CaretRightOutlined class={[styles.icon, itemZ.expand && styles.expand]} /><span>{indexZ}</span>
                                      </div>
                                    </a-dropdown>
                                    <div class={[styles.levelBox, styles['pl-20']]} style={{ display: itemZ.expand ? 'flex' : 'none' }}>
                                      <div class={styles.level}>
                                        <span>Note:</span><span>{itemZ.Note}</span>
                                      </div>
                                      <div class={styles.level}>
                                        <span>Velocity:</span><span>{itemZ.Velocity}</span>
                                      </div>
                                      <div class={styles.level}>
                                        <span>duration:</span><span>{itemZ.duration}</span>
                                      </div>
                                    </div>
                                  </div>
                                ))
                              }
                            </div>
                          ))
                        }
                      </div>
                    ))
                  }
                </div>
              </a-form-item> : <a-form-item label="内容" name="contentStr">
                <a-textarea v-model:value={state.form.contentStr} placeholder="请输入内容" />
              </a-form-item>
            }
          </a-form>
        </div>
        <div class={styles.footer}>
          <a-button type="primary" onClick={() => { submit() }}>提交</a-button>
        </div>
      </div >
    )
  }
})